#pragma once

#include "Reactor.hpp"
#include "Util.hpp"
#include <vector>
#include <cerrno>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>

#define ONCE_SIZE 128

// 1:本轮读取完成
//-1：读取出错
// 0：对端关闭链接
static int RecverCore(int sock, std::string &inbuffer)
{
    while (true)
    {
        char buffer[ONCE_SIZE];
        ssize_t s = recv(sock, buffer, ONCE_SIZE, 0);
        if (s > 0)
        {
            buffer[s] = '\0';
            //读取成功
            inbuffer += buffer;
        }
        else if (s < 0)
        {
            if (errno == EINTR)
            {
                // IO被信号打断，概率很低
                continue;
            }
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
                // 1、读完，底层没数据了
                return 1; // success
            }
            // 2、读取出错
            return -1;
        }
        else
        {
            // s == 0
        }
    }
}

int Recver(Event *evp)
{
    // 1.真正的读取
    int result = RecverCore(evp->sock, evp->inbuffer);
    if (result <= 0)
    {
        //差错处理
        if (evp->errorer)
        {
            evp->errorer(evp);
        }
        return -1;
    }
    // 2.分包 -- 一个或多个报文 -- 解决粘包问题
    std::vector<std::string> tokens;
    std::string sep = "X";
    SplitSegment(evp->inbuffer, &tokens, sep);
    // 3.反序列化 -- 针对一个报文 -- 提取有效参与计算或者存储的信息
    for (auto &seg : tokens)
    {
        std::string data1, data2;
        if (Deserialize(seg, &data1, &data2))
        {
            // 4.业务逻辑 -- 得到结果
            int x = atoi(data1.c_str());
            int y = atoi(data2.c_str());
            int z = x + y;

            // 5.构建响应 -- 添加到evp->outbuffer
            std::string res = data1;
            res += "+";
            res += data2;
            res += "=";
            res += std::to_string(z);
            res += sep;

            evp->outbuffer += res;
        }
    }

    // 6.尝试直接或间接进行发送
    if (!evp->outbuffer.empty())
    {
        //开启对应读写开关
        evp->R->EnableRW(evp->sock, true, true);
    }
    return 0;
}

// 1:数据全部发完
// 0:数据没发完，但是不能继续发送，下次再发
//-1:发送失败
int SenderCore(int sock, std::string &outbuffer)
{
    while (true)
    {
        int total = 0; //本轮累计发送的数据量
        const char *start = outbuffer.c_str();
        int size = outbuffer.size();
        ssize_t curr = send(sock, start + total, size - total, 0);
        if (curr > 0)
        {
            total += curr;
            if (total == size)
            {
                //全部发送完成
                outbuffer.clear();
                return 1;
            }
        }
        else
        {
            if (errno == EINTR)
                continue;
            //数据没有发完，但是无法继续发送
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
                outbuffer.erase(0, total);
                return 0;
            }
            return -1;
        }
    }
}

int Sender(Event *evp)
{
    int result = SenderCore(evp->sock, evp->outbuffer);
    // 1:数据全部发完
    // 0:数据没发完，但是不能继续发送，下次再发
    //-1:发送失败
    if (result == 1)
    {
        //全部发完，可以关闭发送缓冲区
        evp->R->EnableRW(evp->sock, true, false); //按需设置
    }
    else if (result == 0)
    {
        //什么都做不了
        evp->R->EnableRW(evp->sock, true, true); //按需设置
    }
    else
    {
        if (evp->errorer)
        {
            evp->errorer(evp);
        }
    }
}

int Errorer(Event *evp)
{
    evp->R->DeleteEvent(evp);
}